package com.fudan.framework.web.controller;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import com.fudan.framework.annotation.PAdd;
import com.fudan.framework.annotation.PDelete;
import com.fudan.framework.annotation.PUpdate;
import com.fudan.framework.annotation.PView;
import com.fudan.framework.annotation.Permissions;
import com.fudan.framework.base.DaoService;

/**
 * 功能接口的父类，封装通用的权限操作
 * @author Xuxinxing
 *
 * @param <T>
 */
public interface FunctionalController<T> {
	public final String SUCCESS = "操作成功";
	public final String ERROR = "error";

	public final Integer SUCCESS_CODE = 0;
	public final Integer SYSTEM_ERROR_CODE = 500;
	public final Integer ADD_ERROR_CODE = 100;
	public final Integer DELETE_ERROR_CODE = 103;
	public final Integer FIND_ERROR_CODE = 101;
	public final String FIND_ERROR_MSG = "查找失败";
	public final Integer UPDATE_ERROR_CODE = 102;
	public DaoService<T> injectService();
    @SuppressWarnings("unchecked")
    default public Class<T> getActualClass(Class<?> clz) {
        Type[] genericInterfaces = this.getClass().getGenericInterfaces();
        for (Type type : genericInterfaces) {
        	if(type instanceof ParameterizedType) {
        		if(((ParameterizedType) type).getRawType() == clz) {
        			try {
						return (Class<T>) Class.forName(((ParameterizedType)type).getActualTypeArguments()[0].getTypeName());
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
						throw new RuntimeException("泛型无法创建", e);
					}
        		}
        	}
		}
        throw new RuntimeException("不能获取泛型信息");
    }
    
    default public void checkPermission(String action) {
        Subject subject = SecurityUtils.getSubject();
        Class<?> realClass = this.getClass();
        String permissionCode = null;
        String[] perStr = null;
        try {
            Permissions permissions = this.getClass().getAnnotation(Permissions.class);
            if (permissions != null) {
                perStr = permissions.value();
            }
        } catch (SecurityException e1) {
            e1.printStackTrace();
        }
        switch (action) {
            case "add": {
                permissionCode = extractPermissionCode(perStr, 0);
                PAdd padd = realClass.getAnnotation(PAdd.class);
                if (padd != null) {
                    permissionCode = padd.value();
                }
                break;
            }
            case "delete": {
                permissionCode = extractPermissionCode(perStr, 1);
                PDelete pDelete = realClass.getAnnotation(PDelete.class);
                if (pDelete != null) {
                    permissionCode = pDelete.value();
                }
                break;
            }
            case "update": {
                permissionCode = extractPermissionCode(perStr, 2);
                PUpdate pUpdate = realClass.getAnnotation(PUpdate.class);
                if (pUpdate != null) {
                    permissionCode = pUpdate.value();
                }
                break;
            }
            case "find": {
                permissionCode = extractPermissionCode(perStr, 3);
                PView pView = realClass.getAnnotation(PView.class);
                if (pView != null) {
                    permissionCode = pView.value();
                }
                break;
            }
            default: {
                break;
            }
        }
        if (permissionCode != null && !"".equals(permissionCode)) {
            subject.checkPermission(permissionCode);
        }
    }
    default String extractPermissionCode(String[] codes, int index) {
        if (codes == null || codes.length != 4 || index < 0 || index > 3) {
            return null;
        }
        return codes[index];
    }
}
